home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Tech Arsenal 1
/
Tech Arsenal (Arsenal Computer).ISO
/
tek-04
/
ddj0492.zip
/
HANDPRIN.ASC
< prev
next >
Wrap
Text File
|
1992-03-10
|
5KB
|
138 lines
_YOUR OWN HANDPRINTING RECOGNITION ENGINE_
by Ron Avitzur
[LISTING ONE]
/*****************************************************************
A Writer-Dependent Hand-printing Recognizer -- by Ron Avitzur, 1991.
This is not the complete code. See the accompanying article for
a description of other necessary modules.
*****************************************************************/
typedef struct { short num_items; void *items[]; } *List;
typedef struct { short code; List strokes; } GesturePattern
typedef struct { char is_dot; List s[5]; } StrokePattern;
typedef struct {
Point Ink[MAX_POINTS],
P[MAX_N];
short Ink_Num,
N,
T[MAX_N],
IsDot;
unsigned long S[5];
double Aspect_Ratio;
long Xmax,Xmin,
Ymax,Ymin,
Height,Width,
XmaxT,XminT,
YmaxT,YminT,
HeightT,WidthT;
long start_time,end_time;
List matches;
} StrokeData,
*StrokePtr;
ProcPtr HashFunctions[] = { Fxn1,Fxn2,Fxn3,Fxn4,Fxn5 };
char Bits[] = {2,2,3,2,2};
#define DOT_THRESHHOLD (Wacom?80:4)
#define PT_SEP_POST (Wacom?40:4)
/****************************************************************/
void Analyze(register StrokePtr theStroke) {
char i,s[100];
Simplify();
for (i = 0; i < 5; i++) {
HashFunction[i](s,theStroke);
ConvertStringToLong(s,&S[i],Bits[i]);
}
theStroke->IsDot =
((theStroke->Height < DOT_THRESHHOLD
&&
theStroke->Width < DOT_THRESHHOLD)
|| N == 1);
}
/****************************************************************/
void Simplify(StrokePtr theStroke,Point *Ink,short N) {
Point Q[MAX_POINTS];
short min_dx = theStroke->Width / 8,
min_dy = theStroke->Height / 8;
if (theStroke->Aspect_Ratio < 0.2) min_dy = theStroke->Height;
if (theStroke->Aspect_Ratio > 5.0) min_dx = theStroke->Width;
theStroke->N = Process3(theStroke->P,Ink,N,min_dx,min_dy);
ComputeT(theStroke);
}
/****************************************************************/
void ComputeT(StrokePtr theStroke) {
register short *T = theStroke->T;
register Point *P = theStroke->P;
register short i,N = theStroke->N;
for (i = 0; i < N - 1; i++)
T[i] = ATAN2(P[i+1].v-P[i].v,P[i+1].h-P[i].h);
}
/****************************************************************/
short Process3(register Point *P, register Point *Q,
short num,short xd, short yd) {
register short i,n;
register short dx,dy;
n = 0;
P[0] = Q[0];
for (i = 1; i < num - 1; i++) {
dx = Q[i].h - P[n].h; dx = ABS(dx);
dy = Q[i].v - P[n].v; dy = ABS(dy);
if (dx + dy < PT_SEP_POST) continue;
if (dx < xd && dy < yd) continue;
n++;
P[n] = Q[i];
}
dx = Q[num - 1].h - P[n].h;
dy = Q[num - 1].v - P[n].v;
if (ABS(dx) + ABS(dy) > PT_SEP_POST)
n++;
P[n] = Q[num - 1];
return n + 1;
}
/****************************************************************/
/* These five lines determine what the features actually are. */
#define Feature1(t) ('0' + ((t + 10 + 45 + 180) / 90) % 4)
#define Feature2(t) ('0' + ((t + 10 + 00 + 180) / 90) % 4)
#define Feature3(t) ('0' + ((t + 10 + 22 + 180) / 45) % 8)
#define Feature4(p) ('0' + (4*((p).h - theStroke->XminT) /theStroke->WidthT))
#define Feature5(p) ('0' + (4*((p).v - theStroke->YminT) /theStroke->HeightT))
/****************************************************************/
#define FOO(name,fxn,type,array,end) \
void name(char *s,StrokePtr theStroke) \
{ \
register short i,d,n = 0; \
register type *T = theStroke->array; \
s[0] = fxn(*T++); \
i = theStroke->N - end; \
while (i-- > 0) { \
d = fxn(*T++); \
if (s[n] != d) \
s[++n] = d; \
} \
s[++n] = 0; \
}
FOO(Fxn1,Feature1,short,T,2)
FOO(Fxn2,Feature2,short,T,2)
FOO(Fxn3,Feature3,short,T,2)
FOO(Fxn4,Feature4,Point,P,1)
FOO(Fxn5,Feature5,Point,P,1)
/****************************************************************/
void ConvertStringToLong(char *s,unsigned long *np,short bits) {
unsigned long n = 0;
short i,len = strlen(s);
s[len] = s[len-1];
if (len > 32/bits) len = 32/bits;
for (i = 0; i <= len; i++)
n = (n << bits) + s[len - i] - '0';
*np = n;
}